package com.darren.archive.interceptor;

import com.darren.archive.entity.LoginRecord;
import com.darren.archive.entity.LoginRecord.LoginType;
import com.darren.archive.entity.SysUser;
import com.darren.archive.service.LoginRecordService;
import com.darren.archive.service.SysUserService;
import com.darren.framework.Exception.ArchiveException;
import com.darren.framework.entity.AppSession;
import com.darren.framework.entity.TokenEntity;
import com.darren.framework.utils.JWTUtil;
import com.darren.framework.utils.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;


public class TokenInterceptor implements HandlerInterceptor {

    protected Logger logger = LogManager.getLogger(getClass());

    @Resource
    private LoginRecordService loginRecordService;

    @Autowired
    private SysUserService userService;

    private List<String> excludes;

    public List<String> getExcludes() {
        return excludes;
    }

    public void setExcludes(List<String> excludes) {
        this.excludes = excludes;
    }

    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response, Object obj, Exception arg3)
            throws Exception {

    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object arg2, ModelAndView modelAndView) {
        if (!StringUtils.isNull(modelAndView)) {
            System.out.println("****************************************************************************************************");
            System.out.println("========= Redirect Path (Next View):========= " + modelAndView.getViewName());
            System.out.println("****************************************************************************************************");
        }
        AppSession appSession = (AppSession) request.getAttribute("appSession");
        if (appSession != null && appSession.isUpdated()) {
            LoginRecord loginRecord = (LoginRecord) request.getAttribute("loginRecord");
            try {
                loginRecord.setApplicationSession(appSession);
                loginRecordService.update(loginRecord);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }
        request.removeAttribute("user");
        request.removeAttribute("appSession");
        request.removeAttribute("loginRecord");
    }

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) {
        String requestUri = request.getRequestURI();
        String projectName = request.getContextPath();
        //放行exceptUrls中配置的url
        for (String url : excludes) {
            if (url.endsWith("/**")) {
                if (requestUri.startsWith(url.substring(0, url.length() - 3))) {
                    return true;
                }
            } else if (requestUri.startsWith(url) || requestUri.startsWith(projectName + url)) {
                return true;
            }
        }
        String accessToken = request.getHeader("accessToken");
        logger.info("accessToken:{}", accessToken);
        TokenEntity tokenEntity = JWTUtil.unSignAccessJWT(accessToken, TokenEntity.class);
        LoginRecord loginRecord = loginRecordService.findById(tokenEntity.getId());
        if (loginRecord == null) {
            throw new ArchiveException("登陆失效，请重新登陆.");
        }
        if (!LoginType.USER.getDescription().equals(loginRecord.getLoginType())) {
            throw new ArchiveException("非法请求。");
        }
        SysUser user = userService.findById(loginRecord.getLoginId());
        if (user != null) {
            throw new ArchiveException("用户不存在，或者已被删除。");
        }
        request.setAttribute("user", user);
        AppSession appSession = null;
        try {
            appSession = loginRecord.getApplicationSession();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        if (!accessToken.equals(appSession.getAttribute("accessToken"))) {
            throw new ArchiveException("token 已废弃。");
        }
        appSession.resetUpdated();
        response.setHeader("accessToken", accessToken);
        request.setAttribute("appSession", appSession);
        request.setAttribute("loginRecord", loginRecord);
        return true;
    }
}
